/*
 * @Author: i@rysa.cn
 * @Date: 2022-05-14 16:42:23
 * @LastEditTime: 2022-05-14 16:55:47
 * @LastEditors: i@rysa.cn
 * @Description:
 * @FilePath: \go-utils\wechat\mp\jssdk\jssdk.go
 */
package jssdk

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"gitee.com/rysa/go-utils/request"
	"gitee.com/rysa/go-utils/strutil"
	"gitee.com/rysa/go-utils/wechat/mp/accesstoken"
	"gitee.com/rysa/go-utils/wechat/mp/mpconfig"
	"gitee.com/rysa/go-utils/wechat/mp/params"
	"gitee.com/rysa/go-utils/wechat/utils"
)

const (
	jssdkKey = "mp_jsapi_ticket"
)

type jssdk struct {
	*mpconfig.MpConfig
}

func NewJssdk(cfg *mpconfig.MpConfig) *jssdk {
	return &jssdk{cfg}
}

func (mp *jssdk) GetJssdkFromTencent() error {
	token, err := accesstoken.GetAccessToken(mp.MpConfig)
	if err != nil {
		return err
	}
	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi", token)
	req := request.NewRequest()
	res, err := req.Get(url)
	if err != nil {
		return err
	}
	var result params.JsapiTicket
	err = json.Unmarshal(res.Body(), &result)
	if err != nil {
		return err
	}
	if result.Errcode != 0 {
		return errors.New(result.Errmsg)
	}
	cacheKey := jssdkKey
	if mp.JssdkKey != "" {
		cacheKey = mp.JssdkKey
	}
	return mp.Cache.Set(cacheKey, result.Ticket, result.ExpiresIn)
}

func (mp *jssdk) GetJssdkConfig(path string) params.JsapiSignature {
	cacheKey := jssdkKey
	if mp.JssdkKey != "" {
		cacheKey = mp.JssdkKey
	}
	if !mp.Cache.IsExist(cacheKey) {
		err := mp.GetJssdkFromTencent()
		if err != nil {
			return params.JsapiSignature{
				Errcode: -1,
				Errmsg:  err.Error(),
			}
		}
	}
	ticket, err := mp.Cache.Get(cacheKey)
	if err != nil {
		return params.JsapiSignature{
			Errcode: -1,
			Errmsg:  err.Error(),
		}
	}
	timestamp := time.Now().Unix()
	noncestr := strutil.GetRandomString(10)
	pre := params.JsapiSignature{
		Timestamp:   timestamp,
		NonceStr:    noncestr,
		JsapiTicket: ticket,
		Url:         path,
	}
	str, err := utils.GetWechatSign(pre, "json", "")
	if err != nil {
		return params.JsapiSignature{
			Errcode: -1,
			Errmsg:  err.Error(),
		}
	}
	pre.Signature = strutil.Sha1(str)
	pre.AppId = mp.Appid
	return pre
}
